#include "journal.h"
#include "login.h"
#include "crypt.h"
#include "xml.h"
#include "simple.h"
#include "settings.h"
#include "cryptography.h"
#include "plugins.h"
#include "diary.h"


int elog_crypt_decrypt(unsigned char *data, unsigned int len)
{
	if (!viewKey()) {	//we need to set a key!
		if (create_login_window(ELOG_LGN_MODE_SWITCH))
			return 1;
	}
	decryptText(data, len);

	return 0;
}

int elog_crypt_encrypt(unsigned char *data, unsigned int len)
{
	if (!viewKey()) {	//we need to set a key!
		if (create_login_window(ELOG_LGN_MODE_SWITCH))
			return 1;
	}
	encryptText(data, len);


	return 0;
}

struct dict *elog_crypt_open_dry_noTxt(const char *fileName)
{
	struct dict *doc = elog_dry_open(fileName);
	if (!doc)
		return NULL;

	dict_set(doc, "fileName", CPY_STR(fileName));
	dict_set_free(doc, "fileName", 1);
	dict_set_hidden(doc, "fileName", 1);
	 
	char *encType = dict_get(dict_get(doc, "file_info"), "encType"); 
	if (encType) {
		//if, file is encrypted and the journal says no encryption:
		if (encType[0] != elog_journ_current()->settings->encryption[0] 
			&& encType[0] == 'A') {	
			if (create_login_window(ELOG_LGN_MODE_RECOVER)) {	//first try to recover the file
				elog_io_close(dict_get(doc, "handle"));
				dict_unref(doc);
				return NULL;
			} else {
				elog_set_set_str("encryption_method",
						 "AES");
				if (elog_journ_current()->settings->
				    encryption)
					free(elog_journ_current()->
					     settings->encryption);
				elog_sp_cat(&
					    (elog_journ_current()->
					     settings->encryption), "AES",
					    NULL);
			}
		}
		if (encType[0] == 'A' && !viewKey()) {
			if (create_login_window(ELOG_LGN_MODE_RECOVER)) {
				elog_io_close(dict_get(doc, "handle"));
				dict_unref(doc);
				return NULL;
			}
		}
		//If, the file is for encryption and the journal
		//isn't then we'll make this an encrypted journal.
		//If the file is encrypted and there's no key
		//We'll generate one.  
	}

	if ((*(int *)dict_get(doc, "version")) >= 3)	//backwards compat code.
	{
		if (encType[0] == 'A')
			if (elog_crypt_decrypt
			    ((unsigned char *) dict_get(doc, "subject"),
			     (*(int *)dict_get(doc, "lenSubject")))) {
				dict_unref(doc);
				return NULL;
			}
	}

	return doc;
}

struct dict *elog_crypt_open_dry(const char *fileName)
{
	struct dict *doc = elog_crypt_open_dry_noTxt(fileName);
	if (!doc)
		return NULL;
	unsigned int len;
	unsigned char *dat = elog_io_readRestofFile(dict_get(doc, "handle"), &len);
	elog_io_close(dict_get(doc, "handle"));
	dict_remove(doc, "handle");
	
	
	char *encType = dict_get(dict_get(doc, "file_info"), "encType");
	if (encType) {
		if (encType[0] == 'A') {
			if (elog_crypt_decrypt(dat, len)) {
				dict_unref(doc);
				free(dat);
				return NULL;
			}
		}
	} else if (elog_journ_current()->settings->encryption[0] == 'A') {
		if (elog_crypt_decrypt(dat, len)) {
			dict_unref(doc);
			free(dat);
			return NULL;
		}
	}

	dict_set(doc, "entry text", elog_sp_toChar(dat, len));
	dict_set_free(doc, "entry text", 1);
	dict_set_type(doc, "entry text", DICT_TYPE_OBJ);

	return doc;
}



int elog_crypt_save_dry(struct elog_crypt_save *save)
{
	unsigned int len = save->len;
	unsigned char *txt = save->txt;
	struct dict *current = save->doc;
	dict_remove(current, "fileName");

	dict_check(current, "file_info", "subject", 
				"lenSubject", "entry text", NULL);

	//current->lenSubject = strlen(save->doc->subject)+1;
 
	if (save->enc[0] == 'A') {
		elog_crypt_encrypt(txt, len);
		elog_crypt_encrypt(
			elog_sp_toUnsignedChar(dict_get(save->doc, "subject"),
				    (unsigned int *)dict_get(save->doc, "lenSubject")),
			(*(int *)dict_get(save->doc, "lenSubject")));
	}
	dict_set(dict_get(current, "file_info"), "encType", CPY_STR(save->enc));
	dict_set_free(dict_get(current, "file_info"), "encType", 1);


	/*Calling plugins */
	dict_set(current, "entry text", elog_sp_toChar(txt, len));
	struct dict *plgn = dict_new();
	{
		dict_set(plgn, "doc", current);
		dict_set_type(plgn, "doc", DICT_TYPE_DCT);
		dict_set_free(plgn, "doc", 1);
	}
	elog_plgn_call_all("___save", plgn);
	dict_unref(plgn);

	dict_set_free(current, "entry text", 0);
	dict_remove(current, "entry text");
	/*end plugins */


	dict_set(current, "last_edit", elog_io_date());
	dict_set_free(current, "last_edit", 1);


	elog_dry_save(dict_get(current, "fileName"), current, txt, len);


	free(txt);
	dict_unref(current);

	free(save);
	return 0;
}
